const sharp = require("sharp");
const fs = require("fs");
const {
    resolve,
    find,
    saveFile,
    mkdir,
    exists,
    copyFile,
} = require("../tools/file");
const {resizeAndSave, deltaOf} = require("../tools/image");
const {make_ios, make_Android} = require("./ios");
module.exports = {
    initFlutter,
    makeFlutter,
    make,
    makeFolder,
};

const basePath = '/lib/assets/imgs';
const basePathYml = 'lib/assets/imgs';
const fmakerFilePath = `${basePath}/fmaker`;

/**
 * 在 fmaker init 时执行
 * @param flutterProjectPath
 * @returns {Promise<void>}
 */
async function initFlutter(flutterProjectPath = process.cwd()) {
    //初始化创建 /lib/assets/imgs  和 /lib/assets/imgs/fmaker
    await mkdir(`${flutterProjectPath}${basePath}`);
    await mkdir(`${flutterProjectPath}${fmakerFilePath}`);

    // let android = `${flutterProjectPath}${fmakerFilePath}/android_icon.png`;
    // let ios = `${flutterProjectPath}${fmakerFilePath}/ios_icon.png`;
    // let img = `${flutterProjectPath}${fmakerFilePath}/example@3x.png`;
    //
    // await copyFile(resolve("../assets/ic_launcher.png"), android);
    // await copyFile(resolve("../assets/ios.png"), ios);
    // await copyFile(resolve("../assets/example@3x.png"), img);

    console.log(
        `已经增加示例资源:${android},\n${ios},\n${img}\n查看这些文件，最好替换他们,再来试试 fmaker build`
    );
}

const execSync = require('child_process').execSync

/**
 * 检查当前项目是否为flutter项目
 * @param flutterProjectPath
 * @returns {Promise<unknown>}
 */
async function flutterCheck(flutterProjectPath) {
    let isFlutter = await exists(`${flutterProjectPath}/pubspec.yaml`);
    if (!isFlutter) {
        console.log(
            `${flutterProjectPath}/pubspec.yaml 不存在`,
            "你必须在flutter目录下运行"
        );
        return false;
    }
    return isFlutter;
}

/**
 * 检查资源文件是否初始化
 * @param flutterProjectPath
 * @returns {Promise<void>}
 */
async function initDirCheck(flutterProjectPath) {
    let isInit = await exists(`${flutterProjectPath}${fmakerFilePath}`);
    await mkdir(`${flutterProjectPath}${basePath}`);
    await mkdir(`${flutterProjectPath}${fmakerFilePath}`);
    await mkdir(`${flutterProjectPath}${fmakerFilePath}/base_module`);
    let files = await find(`${flutterProjectPath}/lib/module`);
    console.log("files", files);
    for (let i = 0; i < files.length; i++) {
        let fileName = getFileName(files[i]);
        console.log("检查资源文件是否初始化", fileName);
        await mkdir(`${flutterProjectPath}${fmakerFilePath}/${fileName}`);
    }
    return isInit;
}

/**
 * 获取文件名
 * @param filePath
 * @returns {*}
 */
function getFileName(filePath) {
    let fileName = filePath.substring(
        filePath.lastIndexOf("/") + 1,
        filePath.length
    );

    return fileName.replace(/@(\S*)[Xx]/g, "").replace(/\.\S*$/, "");
}


/**
 * 创建图标
 * @param flutterProjectPath
 * @returns {Promise<boolean>}
 */
async function makeFolder(flutterProjectPath = process.cwd()) {
    //检查是否为flutter项目
    let isFlutter = await flutterCheck(flutterProjectPath);
    if (!isFlutter) return;
    let hasIcon = await exists(`${flutterProjectPath}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png`);
    if (!hasIcon) {
        console.log(
            `ios icon 不存在`,
            "必须在flutter工程下运行，fmaker将自动获取iOS项目下的图标"
        );
        return false;
    }

    // 设置图标的脚本的位置
    let shellPath = resolve("../assets/fileicon");

    // 定义
    let size = 256;
    let iconSize = 120;
    let muti = 2;
    // 图包素材
    let folderIcon = sharp(resolve("../assets/folder.png")).resize(size * muti, size * muti);
    let rawIcon = sharp(
        `${flutterProjectPath}/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png`
    ).resize(iconSize * muti, iconSize * muti);

    let iconShape = sharp(resolve("../assets/shape.png"));
    let iconBack = sharp(resolve("../assets/back.png"));


    let icon = iconShape.resize(iconSize * muti, iconSize * muti).composite([{
        input: await rawIcon.toBuffer(),
        left: 0,
        top: 0,
        blend: "in"
    }]);

    let result = await folderIcon.composite([
        {
            input: await iconBack.resize(128 * muti, 128 * muti).toBuffer(),
            top: 71 * muti,
            left: 64 * muti,
        },
        {
            input: await icon.toBuffer(),
            top: 75 * muti,
            left: 68 * muti,
        },
    ]).toBuffer();

    let targetFilePath = `${flutterProjectPath}/_icon.png`;
    console.log('生成图标中...')
    await saveFile(targetFilePath, result);
    let res = execSync(`${shellPath} set ${flutterProjectPath} ${targetFilePath}`).toString();
    console.log('正在设置图标:', res)
    console.log('图标设置成功')

    console.log('\n清理...')
    fs.rmSync(targetFilePath);
    console.log('清理完成')

    // 处理.gitignore
    console.log('\n尝试添加 .gitignore')
    let gitignore = fs.readFileSync(`${flutterProjectPath}/.gitignore`, {encoding: 'utf-8'});
    // console.log(gitignore);
    if (gitignore.indexOf('\nIcon?\n') === -1) {
        gitignore = gitignore + '\n\n# fmaker folder icon\nIcon?\n'
        fs.writeFileSync(`${flutterProjectPath}/.gitignore`, gitignore);
        // console.log(gitignore);
        console.log('.gitignore 添加完成')
    } else {
        console.log('无需添加.gitignore')
    }
}

/**
 *  创建flutter资源
 * @param flutterProjectPath
 * @returns {Promise<void>}
 */
async function makeFlutter(flutterProjectPath = process.cwd()) {
    //检查是否为flutter项目
    let isFlutter = await flutterCheck(flutterProjectPath);
    if (!isFlutter) return;
    //检查资源文件是否初始化
    let isInit = await initDirCheck(flutterProjectPath);
    if (!isInit) return;
    //检查fmaker文件夹下有多少模块
    let files = await find(`${flutterProjectPath}${fmakerFilePath}`);
    console.log("文件夹下模块", files);
    for (let i = 0; i < files.length; i++) {
        await _generatePicture(flutterProjectPath, files[i], i, files.length);
    }
}

let assetsListString;

async function _generatePicture(flutterProjectPath, moduleFilePath, index, moduleFiles) {
    let moduleName = getFileName(moduleFilePath);
    //查询模块下有多少图片
    let pictureFiles = await find(`${moduleFilePath}`);

    if (pictureFiles.length === 0) {
        console.log(`请先添加图片到${moduleFilePath}目录`);
        return;
    }
    let allFileName = [];
    for (const imgPath of pictureFiles) {
        if (imgPath.indexOf(".png") < 1) {
            continue;
        }

        await make(imgPath, async (imageName, delta, isCheck) => {
            imageName = moduleName + "_" + imageName;
            if (delta === 1) {
                if (!isCheck) {
                    // console.log("创建资源图", imageName);
                    allFileName.push(imageName);
                }
                return `${moduleFilePath}/${imageName}.png`;
            }
            await mkdir(`${flutterProjectPath}${basePath}/${delta}.0x/`);
            return `${flutterProjectPath}${basePath}/${delta}.0x/${imageName}.png`;
        });
    }
    // console.log("资源目录：", allFileName);

    /// 保存到yaml
    assetsListString = allFileName
        .map((name) => {
            return `    - ${basePathYml}/${name}.png`;
        })
        .join("\n");

    // assetsListString = `    # fmaker-${moduleName}\n` + assetsListString + `\n    # fmaker-${moduleName}-end`;
    let replaceSuccess = false;

    if (index === 0) {
        replaceSuccess = _replaceStringInFile(
            `${flutterProjectPath}/pubspec.yaml`,
            /(# fmaker)[\w\W]*(# fmaker-end)/g,
            "# fmaker\n    # fmaker-end"
        );
    }
    let generateSuccess = _replaceStringInFile(
        `${flutterProjectPath}/pubspec.yaml`,
        "# fmaker",
        "# fmaker\n" +
        assetsListString +
        (!replaceSuccess && index === 0 ? "\n    # fmaker-end" : "")
    );

    if (!generateSuccess) {
        console.log(
            "\n在pubspec.yaml中没有找到生成标记，请添加‘# fmaker’标记！！\n"
        );
    }

    /// 保存到r.dart
    await mkdir(`${flutterProjectPath}/lib`);

    let rContentListString = allFileName
        .map((name) => {
            let dartName = _toHump(name);
            return (
                `  /// ![](${basePath}/${name}.png)\n` +
                `  static final String ${dartName} = '${basePathYml}/${name}.png';`
            );
        })
        .join("\n");
    let rname = "R" + _toFirstLetter(_toHump(moduleName));
    let rContent = `class ${rname} {\n${rContentListString}\n}`;
    fs.writeFileSync(`${flutterProjectPath}/lib/r_${moduleName}.dart`, rContent);
}

// 生成一张图片的低倍率版本
async function make(filePath, filePathBuilder) {
    if (!filePathBuilder) {
        // 文件路径创建
        filePathBuilder = async (imageName, delta) => {
            console.log("采用默认生成");
            return `${process.cwd()}/${imageName}@${delta}x.png`;
        };
    }

    let imageName = getFileName(filePath);

    // 获取倍率
    let delta = deltaOf(filePath);
    // console.log(`\n正在生成:${imageName} 倍率:${delta}`);
    let image = sharp(filePath);
    let metadata = await image.metadata();

    //先预先检查一下
    let preCheck = await filePathBuilder(imageName, 1, true);
    if (!preCheck) {
        return;
    }

    for (let i = delta; i > 0; i--) {
        let size = parseInt((metadata.width / delta) * i);
        let targetPath = await filePathBuilder(imageName, i);
        //不生成一倍图
        if (i === 1) continue;
        await resizeAndSave(image, size, targetPath);
    }
}

/**
 * 下划线转换驼峰
 * @param name
 * @returns {*}
 * @private
 */
function _toHump(name) {
    return name.replace(/[\_\-\+:\(\)\[\] ](\w)/g, function (all, letter) {
        return letter.toUpperCase();
    });
}

/**
 * 下划线转换驼峰
 * @param name
 * @returns {*}
 * @private
 */
function _toFirstLetter(name) {
    let first = name[0].toUpperCase();
    return first + name.substr(1, name.length);
}

function _replaceStringInFile(file, target, replace) {
    let content = fs.readFileSync(file, {encoding: "UTF-8"});
    let newContent = content.replace(target, replace);
    fs.writeFileSync(file, newContent);
    return content !== newContent;
}